<?php

/*
 * Copyright (c) 2012 Aalto University and University of Helsinki
 * MIT License
 * see LICENSE.txt for more information
 */

set_include_path(
        get_include_path() . PATH_SEPARATOR . 'lib/easyrdf/lib/'
        . PATH_SEPARATOR . 'lib/');
require_once('EasyRdf.php');

EasyRdf_Namespace::set('onki', 'http://schema.onki.fi/onki#');
EasyRdf_Namespace::set('void', 'http://rdfs.org/ns/void#');
EasyRdf_Namespace::set('pf', 'http://jena.hpl.hp.com/ARQ/property#');
EasyRdf_Namespace::set('ysa_meta', 'http://www.yso.fi/onto/ysa-meta/');
EasyRdf_Namespace::set('kunnat', 'http://www.yso.fi/onto/kunnat/');
EasyRdf_Namespace::set('skosext', 'http://purl.org/finnonto/schema/skosext#');

require_once('model/VocabularyDAO.php');
require_once('model/GenericSparql.php');
require_once('model/LARQSparql.php');

class Model {

  public $vocDAO;

  public function __construct() {
    $this->vocDAO = new VocabularyDAO();
  }

  /**
   * Makes a query into the sparql endpoint for a concept.
   * @param string $vocid vocabulary id eg. 'yso'.
   * @param string $lname the searchterm to use in the search eg. 'cat'.
   * @param string $lang the language to be used in the search eg. 'fi'.
   * @return array
   */
  public function getConceptInfo($vocid, $lname, $lang) {
    try {
      $voc = $this->vocDAO->getVocabulary($vocid);
      $sparql = $voc->getSparql();
    } catch (Exception $e) {
      return;
    }
    if (strstr($lname, 'http')) {
      $uri = urldecode($lname);
    } else {
      $uri = $voc->getConceptURI($lname);
    }

    return $sparql->queryConceptInfo($uri, $voc->getHasGlobalCollections(), $lang, $vocid);
  }

  /**
   *
   * @param type $vocid
   * @return type
   */
  public function getVocabulary($vocid) {
    return $this->vocDAO->getVocabulary($vocid);
  }

  /**
   * Function makes a query into the SPARQL endpoint to determine
   * all the vocabularies available.
   * @param boolean $categories wheter you want everything included in a subarray of
   * a category.
   */
  public function getVocabularyList($categories = true) {
    $cats = $this->vocDAO->getVocabularyCategories();
    $ret = array();
    foreach ($cats as $cat) {
      $catlabel = $cat->getTitle();

      // find all the vocabs in this category
      $vocs = $cat->getVocabularies();

      if (sizeof($vocs) > 0 && $categories)
        $ret[$catlabel] = $vocs;
      elseif (sizeof($vocs) > 0)
        $ret = array_merge($vocs, $ret);
    }
    return $ret;
  }

  /**
   * returns concept's RDF in downloadable format
   * @param string $vocid is concept's vocabulary i.e. in which vocabulary the concept belongs to
   * @param string $lname is concept's 'local name' i.e. 'p12345'
   * @param string $format is the format in which you want to get the result, currently this function supports
   * text/turtle and rdf/xml
   */
  public function getRDF($vocid, $uri, $format) {
    $sparql = $this->vocDAO->getVocabulary($vocid)->getSparql();

    if ($format === 'text/turtle') {
      $retform = 'turtle';
      $serialiser = new EasyRdf_Serialiser_Turtle();
    } else {
      $retform = 'rdfxml';
      $serialiser = new EasyRdf_Serialiser_RdfXml();
    }

    $result = $sparql->queryConceptInfo($uri, $this->vocDAO->getVocabulary($vocid)->getHasGlobalCollections(), null, null, true);

    return $serialiser->serialise($result, $retform);
  }

  /**
   * Makes a SPARQL-query to the endpoint that retrieves concept
   * references as it's search results.
   * @param string $term the term that is looked for eg. 'cat'.
   * @param string $vocid vocabulary id eg. 'yso'.
   * @param string $lang language parameter eg. 'fi' for Finnish.
   * @param int $offset optional parameter for search offset.
   * @param int $maxhits optional paramater for maximum amount of results.
   */
  public function searchConcepts($term, $vocid, $lang, $offset = 0, $limit = DEFAULT_SEARCH_LIMIT) {
    $term = trim($term);
    if ($term == "" || $term == "*")
      return array(); // don't even try to search for empty prefix
    if ($vocid) { // search within vocabulary
      $voc = $this->vocDAO->getVocabulary($vocid);
      $sparql = $voc->getSparql();
    } else { // global search
      $voc = null;
      $sparql = $this->vocDAO->getDefaultSparql();
    }

    $result = $sparql->queryConcepts($term, $lang, $limit, $offset);
    $ret = array();

    foreach ($result as $row) {
      $hit = array();
      $hit['uri'] = $row->s->getUri();

      if ($vocid) // search within vocabulary
        $hit['vocab'] = $vocid;
      else // global search
        $voc = $this->vocDAO->getVocabularyByGraph($row->graph);
      $hit['vocab'] = $voc->getId();

      $hit['localname'] = $voc->getLocalName($row->s->getUri());

      // if uri is a external vocab uri that is included in the current vocab
      if ($hit['localname'] == $hit['uri'])
        $hit['exvocab'] = $this->vocDAO->guessVocabularyFromURI($hit['uri'])->getId();

      $hit['label'] = $row->label->getValue();
      if (isset($row->alabel)) {
        $hit['altlabel'] = $row->alabel->getValue();
      }
      $hit['voc'] = $voc;
      $ret[] = $hit;
    }
    return $ret;
  }

  /**
   * Function for performing a search for concepts and their data fields.
   * @param string $term searchterm eg. 'cat'
   * @param string $vocid which vocabulary is the search done in eg. 'yso'
   * @param string $lang eg. 'fi'
   * @param integer $offset used for offsetting the result set eg. '20'
   * @param integer $limit upper count for the search results eg. '10'
   */
  public function searchConceptsAndInfo($term, $vocid, $lang, $offset = 0, $limit = 20) {
    $hits = $this->searchConcepts($term, $vocid, $lang, $offset, $limit);

    $ret['hit'] = $hits;
    $uris = array();
    foreach ($hits as $hit)
      $uris[] = $hit['uri'];
    if ($vocid) {
      $voc = $this->vocDAO->getVocabulary($vocid);
      $sparql = $voc->getSparql();
      $hgc = $voc->getHasGlobalCollections();
    } else {
      $hgc = false;
      $sparql = $this->vocDAO->getDefaultSparql();
    }
    $ret = $sparql->queryConceptInfo($uris, $hgc, $lang, $vocid);

    // For marking that the concept has been found through an alternative label.
    foreach ($hits as $hit)
      if (isset($hit['altlabel']) && isset($ret[$hit['uri']]))
        $ret[$hit['uri']]->setFoundBy($hit['altlabel']);

    return $ret;
  }

}

?>